package cn.schoolwow.quickdao.module.initial.flow.table;

import cn.schoolwow.quickdao.domain.QuickDAOConfig;
import cn.schoolwow.quickdao.domain.database.ddl.IndexField;
import cn.schoolwow.quickdao.domain.entity.Entity;
import cn.schoolwow.quickdao.domain.entity.Property;
import cn.schoolwow.quickdao.module.database.ddl.action.flow.column.CreateForeignKeyFlow;
import cn.schoolwow.quickdao.module.database.ddl.action.flow.column.CreateTableColumnFlow;
import cn.schoolwow.quickdao.module.database.ddl.action.flow.index.CreateIndexFlow;
import cn.schoolwow.quickdao.module.database.ddl.common.flow.DeleteDatabaseEntityCacheFlow;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;

import java.util.List;

public class CompareAndCreateColumnFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        setDatabaseEntity(flowContext);
        createColumn(flowContext);
        createIndex(flowContext);
    }

    @Override
    public String name() {
        return "比较并创建实体类列";
    }

    private void setDatabaseEntity(FlowContext flowContext){
        QuickDAOConfig quickDAOConfig = flowContext.checkInstanceData(QuickDAOConfig.class);
        Entity entity = (Entity) flowContext.checkData("entity");

        Entity databaseEntity = quickDAOConfig.dao.getDatabaseEntity(entity.tableName);
        if(null==databaseEntity){
            flowContext.brokenCurrentFlow("数据库表不存在!表名:"+entity.tableName);
            return;
        }
        if(!databaseEntity.tableName.equalsIgnoreCase(entity.tableName)){
            throw new IllegalArgumentException("实体类获取错误!预期表名:"+entity.tableName+",实际表名:"+databaseEntity.tableName);
        }
        flowContext.putCurrentFlowData("databaseEntity", databaseEntity);
    }

    private void createColumn(FlowContext flowContext){
        QuickDAOConfig quickDAOConfig = flowContext.checkInstanceData(QuickDAOConfig.class);
        Entity entity = (Entity) flowContext.checkData("entity");
        Entity databaseEntity = (Entity) flowContext.checkData("databaseEntity");

        List<Property> sourcePropertyList = entity.properties;
        for (Property sourceProperty : sourcePropertyList) {
            Property targetProperty = databaseEntity.getPropertyByFieldNameOrColumnName(sourceProperty.column);
            if (null == targetProperty) {
                flowContext.startFlow(new CreateTableColumnFlow())
                        .next(new DeleteDatabaseEntityCacheFlow())
                        .putData("tableName", databaseEntity.tableName)
                        .putData("propertyOption", sourceProperty)
                        .execute();
                targetProperty = databaseEntity.getPropertyByFieldNameOrColumnName(sourceProperty.column);
            }
            if(!quickDAOConfig.databaseOption.openForeignKey){
                continue;
            }
            if(null==sourceProperty.foreignKey){
                continue;
            }
            if(targetProperty.foreignKeyColumn){
                continue;
            }
            flowContext.startFlow(new CreateForeignKeyFlow())
                    .next(new DeleteDatabaseEntityCacheFlow())
                    .putData("tableName", databaseEntity.tableName)
                    .putData("propertyOption", sourceProperty)
                    .execute();
        }
    }

    private void createIndex(FlowContext flowContext){
        Entity entity = (Entity) flowContext.checkData("entity");
        Entity databaseEntity = (Entity) flowContext.checkData("databaseEntity");

        //判断索引是否有新增
        for (IndexField indexField : entity.indexFieldList) {
            boolean exist = false;
            for(IndexField databaseIndexField:databaseEntity.indexFieldList){
                if(databaseIndexField.indexName.equalsIgnoreCase(indexField.indexName)){
                    exist = true;
                    break;
                }
            }
            if(!exist){
                flowContext.startFlow(new CreateIndexFlow())
                        .next(new DeleteDatabaseEntityCacheFlow())
                        .putData("indexField", indexField)
                        .putData("tableName", entity.tableName)
                        .execute();
            }
        }
    }
}
